Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address deprecations in MP metrics for 3.x #4500

Merged
merged 9 commits into from
Jul 12, 2022
Merged

Address deprecations in MP metrics for 3.x #4500

merged 9 commits into from
Jul 12, 2022

Conversation

tjquinno
Copy link
Member

@tjquinno tjquinno commented Jul 8, 2022

Resolves #4371

Background

The gRPC MP metrics component performs special handling for methods which are effectively annotated with @GrpcMethod and also bear a metrics annotation:

  1. The normal metrics interception binding should not apply. gRPC methods are async and the interceptors are sync. gRPC metrics takes care of interceptors for gRPC methods.
  2. Under some gRPC-specific conditions, overridden methods should and in other conditions they should not inherit metrics annotation behavior from a superclass. When they should not, the system must not register the metric which would correspond to that endpoint.

In previous releases

During ProcessAnnotatedType processing, the gRPC MP metrics CDI extension removed the metrics annotation from methods with both @GrpcMethod and a metrics annotation to prevent the normal interceptor binding. This not only prevented the normal metrics interceptor behavior (which is what gRPC really wanted), but it also burdened gRPC with registering the correct metrics with the correct metadata and name; this is because the metrics CDI extension no longer saw the metrics annotations on those gRPC methods and so could not register those metrics itself.

To do this, gRPC MP metrics invoked several methods in and used data structures from MP metrics that should not be exposed, methods and data structures that we had marked as deprecated (to discourage users from relying on them and to remove them once we got around to refactoring things).

Redesign in 3.0.0

Note that these changes are intended for--and tuned to--usage from our own gRPC code. Although they are not intended for use from general user code we cannot prevent that. As a result there are no doc updates (other than JavaDoc) describing the new public interfaces.

Remove the hard binding of our metrics interceptors to the MicroProfile Metrics annotations

Helidon MP metrics has always had an interceptor for each different MP metric annotation. Previously, these were bound directly, by declaration, to the corresponding MP metric annotation.

This PR introduces separate annotations for the interceptor bindings.

The metrics CDI extension code now programmatically adds the correct interceptor binding annotation to each constructor and method if all observers agree that using the normal interceptor is OK. (See below for more about "all observers.")

Clean up the contract between gRPC and metrics

  • Remove (or reduce visibility of) much of the previously public and @Deprecated code.
  • Expose new cleaner public interfaces:
  1. New interface in io.helidon.microprofile.metrics: MetricAnnotationDiscovery

    Exposes information about the discovery of a metrics annotation as applied to an executable (constructor or method). Also allows an observer (see below) to:

    1. Suppress the normal metrics interceptor behavior for the specific combination of metric annotation/executable represented by the discovery object.
    2. Request that the metrics system completely disregard this discovery, preventing even the registration of a metric for it.
  2. In the new package io.helidon.microprofile.metrics.spi:

    1. MetricAnnotationDiscoveryObserver - implementations are invoked with a MetricAnnotationDiscovery object for each discovery of a metrics annotation which applies to an executable.
    2. MetricRegistrationObserver - implementations are notified as each metric inspired by an annotation is registered. (There is no special "event" object here; the SPI method's parameters are the associated discovery and the Metadata, MetricID, and Metric objects for the just-registered metric.)

Change the MP metrics CDI extension

The metrics CDI extension now:

  1. Uses service loading to find, instantiate, and collect all implementations of the two types of observers.
  2. Invokes all discovery observers as the metrics annotations are found. If no observer deactivated the discovery or suppressed the default interceptor behavior, the extension programmatically adds the appropriate interceptor binding annotation to the annotation site.
  3. During metrics registration (later in the CDI lifecycle), checks the corresponding discovery to make sure no discovery observer deactivated it. Then registers the metric and notifies the registration observers.

Modify the gRPC code

  1. Implement the discovery interface to record discoveries and suppress the normal interceptor binding if appropriate, or deactivate the discovery if needed. These decisions are governed by gRPC rules that I've carried over from the old code.

  2. Implement the registration interface to record metrics information gRPC needs for its own interceptor.

  3. Remove the gRPC metrics CDI extension. It is no longer needed.

  4. Update an important test to use @HelidonTest in place of the direct use of the Weld API.5.

    Because the metrics CDI extension now creates all metrics, even gRPC ones, and notifies enrolled observers, the test needs to have the CDI container and the metrics CDI extension running. Just starting the server using @HelidonTest caused failures in the gRPC server extension because of the way some test classes are designed to exercise specific behavior. I got things to work using @HelidonTest and @DisableDiscovery and explicitly adding the CDI extensions required for the test--which does not include the gRPC server CDI extension.

    Getting to this point was a bit challenging and revealed either:

    • a bug in the gRPC code (not in this PR),
    • a test that exercises an unsupported case, or
    • a gap in my understanding.

    The two gRPC experts are both out of the office for several days, so the updated MetricsConfigurerTest class in this PR is not as robust as it might be, but it works correctly. We might revisit this after the gRPC team weighs in. Any changes would not change the existing public interface or behavior of Helidon so we could improve this in a future dot release.

Misc. Notes

I tried to purturb the general structure of the code as little as possible. There might have been ways to consolidate some of the data structures which MetricsCdiExtension manages internally, but that would have been considerably more work without much payoff. We are likely to undergo a significant rewrite of metrics for MP Metrics 5.0 and time was short enough as it was.

@tjquinno tjquinno added this to the 3.0.0 milestone Jul 8, 2022
@tjquinno tjquinno self-assigned this Jul 8, 2022
Copy link
Member

@tomas-langer tomas-langer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tjquinno tjquinno merged commit 5b73cd7 into helidon-io:master Jul 12, 2022
@tjquinno tjquinno deleted the metrics-depr-3.x branch July 12, 2022 17:32
arjav-desai pushed a commit to arjav-desai/helidon that referenced this pull request Jul 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deprecations: MP Metrics
2 participants